/*
 * 这玩意用来模拟生产环境的相机采集
 * 不会创建视频文件，消息系统中的数据都是假的
 * 会自动生成处理结果
 * */
#include "../src/confReader.hpp"
#include "../src/ShareMem.hpp"
#include "../src/POSIX_MsgServer.hpp"
#include "../src/FrameCounter.hpp"
#include "../src/StringRegex.hpp"
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#include <yaml-cpp/yaml.h>
#include <ImageType.hpp>
#include <iostream>
#include <any>
#include <cstring>
#include <fstream>

POSIX_MsgServer* msgServer;
StringRegex* strDecode;

const char* configFilePath="/tmp/HBTY_server_ipc.yaml";
const char* MsgServerName="/HBTY_MSGSERVER_CAMERACOLLEGE";


void Handle_MsgReceive(std::string && recData)
//用于处理消息
{
  if(strDecode->HandleString(recData))
    std::cout<<"New Command "<<recData<<std::endl;
  else
    std::cout<<"Can't Decode Receive Data "<<recData<<std::endl;
}

void CreateEmptyFile(std::filesystem::path path)
{
  std::ofstream createFile(path);
  if(!createFile.is_open())
    std::cout<<"Can't create file in path "<<path<<std::endl;
  createFile.close();
}

std::vector<ShareMem> shareMemList;
ShareMem handleMem("/HBTY_HANDLE_SHAREDMEM",1920*1080*3);

//手动指定相机数据
std::vector<std::string> cameraList={
  "C1527A0090416",
  "C1527A0090431",
  "C1527A0090488",
  "C1527A0090503",
  "C1527A0090539",
};

int main()
{
  //计算基础数据
  long ShareMEMSize=sizeof(ImageType)+1920*1080*3;
  std::cout<<"System Boot ... "<<std::endl;
  //准备引擎
  {
    std::ofstream outputConfig(configFilePath,std::ios::trunc);
    if(!outputConfig.is_open())
      throw std::runtime_error("无法写入配置文件");
    //手动指定图片路径
    int w,h,n;
    unsigned char* testImg=stbi_load("test1080P.jpg",&w,&h,&n,3);
    if(testImg==nullptr || !(w==1920 && h==1080 && n==3))
      throw std::runtime_error("测试图像错误");

    YAML::Node config;
    config["shm_size"]=ShareMEMSize;
    config["num"]=cameraList.size();
    int shareCounter=0;
    shareMemList.reserve(cameraList.size());

    ImageType imgType;
    imgType.width=1920;
    imgType.height=1080;
    imgType.data_size=1920*1080*3;
    imgType.data=nullptr;
    imgType.FrameID=0;
    imgType.TimeStamp=0;

    for(const auto & i : cameraList)
    {
      //生成共享内存名称
      std::string shareMemName=std::string("/HBTY_SHAREMEM_ORIMAGE")+std::to_string(shareCounter++);
      config["shm"].push_back(shareMemName);
      //创建共享内存并写入数据
      void* mem=shareMemList.emplace_back(shareMemName.c_str(),sizeof(ImageType)+1920*1080*3).GetMemory();
      strcpy(imgType.uuid,shareMemName.c_str());
      memcpy(mem,&imgType,sizeof(ImageType));
      memcpy((char*)mem+sizeof(ImageType),testImg,1920*1080*3);
    }
    memcpy(handleMem.GetMemory(),testImg,1920*1080*3);
    stbi_image_free(testImg);
    //创建消息通道
    msgServer=new POSIX_MsgServer(MsgServerName);
    //写入索引
    outputConfig<<config;
    outputConfig.close();
  }
  //准备正则解析引擎
  strDecode=new StringRegex;
  strDecode->append(R"(Record Start ([\w\/]+))",[](std::smatch res){
    std::cout<<"Record Start Path: "<<res[1]<<std::endl;
    //输出空文件,跳过测试阶段
    std::filesystem::path rootPath(res[1]);
    for(const auto & i : cameraList)
    {
      CreateEmptyFile(rootPath/(i+".mkv"));
      CreateEmptyFile(rootPath/(i+".frame"));
    }
  });
  strDecode->append(R"(Record Stop)",[](std::smatch){
  });
  strDecode->append(R"(Monitor Start)",[](std::smatch){
  });
  strDecode->append(R"(Monitor Stop)",[](std::smatch){
  });
  strDecode->append(R"(Status Record)",[](std::smatch){
    msgServer->SendData("True");
  });
  strDecode->append(R"(Status Monitor)",[](std::smatch){
    msgServer->SendData("True");
  });
  std::cout<<"Sytem Ready ..."<<std::endl;

  msgServer->BootReceive(Handle_MsgReceive);

  while(sleep(10)==0)
    ;

  delete msgServer;
}
